package Service

import (
	"github.com/bwmarrin/snowflake"
	"github.com/jinzhu/copier"
	"gorm.io/gorm/clause"
	"log"
	"strings"
	"time"
	"web_back_go/Common"
	"web_back_go/DAO/gorm"
	"web_back_go/DAO/gorm/GormModel"
	"web_back_go/Dto"
	"web_back_go/Util"
	"web_back_go/constants"
)

func SubmitOrders(userId string, mergerOrder Dto.ShopCartOrderMergerDto) []GormModel.TzOrder {
	var orderList []GormModel.TzOrder
	// 通过事务提交订单
	now := Common.GetCurrentTime()
	db := gorm.Db.Begin()
	//设置回退
	defer func() {
		if err := recover(); err != nil {
			log.Println(err)
			db.Rollback()
		}

		db.Commit()

	}()
	// 订单商品参数
	var shopCartOrders []Dto.ShopCartOrderDto = mergerOrder.ShopCartOrders

	var basketIds []int64
	// 商品skuId为key 需要更新的sku为value的map
	var skuStocksMap map[int]GormModel.TzSku = make(map[int]GormModel.TzSku)
	// 商品productId为key 需要更新的product为value的map
	var prodStocksMap map[int]*GormModel.TzProd = make(map[int]*GormModel.TzProd)
	// 把订单地址保存到数据库
	// 创建一个新的 TzUserAddr 实例并让 userAddrOrder 指向它
	userAddrOrder := new(GormModel.TzUserAddr)
	log.Println(&mergerOrder.UserAddr)
	if err := copier.Copy(userAddrOrder, &mergerOrder.UserAddr); err != nil {
		log.Printf("复制属性时出错: %v", err)
		panic("请填写收货地址")
	}
	//手动copy

	if userAddrOrder == nil {
		panic("请填写收货地址")
	}
	userAddrOrder.UserID = userId
	userAddrOrder.CreateTime = now
	userAddrOrder.UpdateTime = now
	db.Save(userAddrOrder)
	// 订单地址id
	var addrOrderId uint64 = userAddrOrder.AddrID
	// 每个店铺生成一个订单
	for _, shopCartOrderDto := range shopCartOrders {
		createOrder(now, userId, &basketIds, skuStocksMap, prodStocksMap, addrOrderId, shopCartOrderDto, &orderList, mergerOrder)
	}
	//删除购物车的商品信息
	if basketIds != nil && len(basketIds) > 0 {

		db.Where("user_id = ? AND basket_id IN ?", userId, basketIds).Delete(&GormModel.TZBasket{})
	}
	// 更新sku库存
	for _, sku := range skuStocksMap {
		if db.Exec("update tz_sku set stocks = stocks - ?, version = version + 1, update_time = NOW() where sku_id = ? and ? <= stocks", sku.Stocks, sku.SkuID, sku.Stocks).RowsAffected == 0 {
			panic("商品：[" + *sku.ProdName + "]库存不足")
		}
	}
	// 更新商品库存
	for _, prod := range prodStocksMap {
		if db.Exec(`update tz_prod set total_stocks = total_stocks - ? ,version = version + 1 where prod_id = ? and ? <= total_stocks`, prod.TotalStocks, prod.ProdID, prod.TotalStocks).RowsAffected == 0 {
			panic("商品：[" + *prod.ProdName + "]库存不足")
		}
	}
	log.Printf("插入的订单:%v\n", orderList)
	// 插入订单
	db.Clauses(clause.OnConflict{
		UpdateAll: true,
	}).CreateInBatches(orderList, 100)
	var orderItems []GormModel.TzOrderItem
	for _, order := range orderList {
		orderItems = append(orderItems, order.OrderItems...)
	}
	// 插入订单项，返回主键
	db.Clauses(clause.OnConflict{
		UpdateAll: true,
	}).CreateInBatches(orderItems, 100)
	return orderList
}

/*
 */
func createOrder(now time.Time, userId string, basketIds *[]int64, skuStocksMap map[int]GormModel.TzSku, prodStocksMap map[int]*GormModel.TzProd, addrOrderId uint64, shopCartOrderDto Dto.ShopCartOrderDto, orders *[]GormModel.TzOrder, mergerOrder Dto.ShopCartOrderMergerDto) {
	// 使用雪花算法生成的订单号
	node, _ := snowflake.NewNode(1) // 节点 ID=1
	id := node.Generate()
	orderNumber := id.String()
	shopId := shopCartOrderDto.ShopId

	// 订单商品名称
	var orderProdName strings.Builder
	var orderItems []GormModel.TzOrderItem
	var shopCartItemDiscounts []Dto.ShopCartItemDiscountDto = shopCartOrderDto.ShopCartItemDiscounts
	for _, shopCartItemDiscount := range shopCartItemDiscounts {
		var shopCartItems []Dto.ShopCartItemDto = shopCartItemDiscount.ShopCartItems
		for _, shopCartItem := range shopCartItems {
			var sku *GormModel.TzSku = checkAndGetSku(shopCartItem.SkuId, &shopCartItem, skuStocksMap)
			var product *GormModel.TzProd = checkAndGetProd(uint64(shopCartItem.ProdId), &shopCartItem, prodStocksMap)
			var orderItem GormModel.TzOrderItem = getOrderItem(now, userId, orderNumber, shopId, &orderProdName, shopCartItem, *sku, *product)
			orderItems = append(orderItems, orderItem)

			//if shopCartItem.BasketId != nil && shopCartItem.BasketId != 0 {
			if shopCartItem.BasketId != 0 {
				*basketIds = append(*basketIds, shopCartItem.BasketId)
			}
		}
	}
	var substringBuilder *strings.Builder = Util.SafeSubstring(&orderProdName, 100)
	var substring string = substringBuilder.String()
	if strings.HasSuffix(substring, constants.COMMA) {
		substring = strings.TrimSuffix(substring, constants.COMMA)
	}
	// 清空 orderProdName
	orderProdName.Reset()
	// 将处理后的 substring 写入 orderProdName
	orderProdName.WriteString(substring)
	// 类型转换：将 int64 转换为 uint64
	convertedShopId := uint64(shopId)

	// 创建一个 uint64 类型的变量并赋值
	var shopIdVar uint64 = convertedShopId
	// 订单信息
	var order = getOrder(now, userId, &addrOrderId, shopCartOrderDto, orderNumber, &shopIdVar, orderProdName, orderItems)
	*orders = append(*orders, order)
	// 插入订单结算表
	var orderSettlement GormModel.TzOrderSettlement
	orderSettlement.UserID = &userId
	IsClearing := 0
	orderSettlement.IsClearing = &IsClearing
	orderSettlement.CreateTime = now

	orderSettlement.OrderNumber = &orderNumber
	orderSettlement.PayAmount = order.ActualTotal
	PayStatus := 0
	orderSettlement.PayStatus = &PayStatus
	Version := 0
	orderSettlement.Version = &Version
	db := gorm.Db
	db.Save(&orderSettlement)
}

/*
checkAndGetSku
@Description: 校验sku信息
*/
func checkAndGetSku(skuId int64, shopCartItem *Dto.ShopCartItemDto, skuStocksMap map[int]GormModel.TzSku) *GormModel.TzSku {
	// 获取sku信息
	db := gorm.Db
	var sku *GormModel.TzSku
	db.Where("sku_id = ?", skuId).First(&sku)
	if sku == nil {
		panic("购物车包含无法识别的商品")
	}
	if *sku.Status != 1 {
		panic("商品[" + *sku.ProdName + "]已下架")
	}
	//-1为无限库存
	if *sku.Stocks != -1 && shopCartItem.ProdCount > *sku.Stocks {
		panic("商品[" + *sku.ProdName + "]库存不足")
	}
	if *sku.Stocks != -1 {
		var mapSku GormModel.TzSku
		mapSku.ProdID = sku.ProdID
		// 这里的库存是改变的库存
		mapSku.Stocks = &shopCartItem.ProdCount
		mapSku.SkuID = sku.SkuID
		mapSku.ProdName = sku.ProdName
		skuStocksMap[int(*sku.SkuID)] = mapSku
	}
	return sku
}

/*
checkAndGetProd
@Description: 校验商品信息
*/
func checkAndGetProd(prodId uint64, shopCartItem *Dto.ShopCartItemDto, prodStocksMap map[int]*GormModel.TzProd) *GormModel.TzProd {
	db := gorm.Db
	var product *GormModel.TzProd
	db.Where("prod_id =?", prodId).First(&product)
	if product == nil {
		panic("购物车包含无法识别的商品")
	}
	if *product.Status != 1 {
		panic("商品[" + *product.ProdName + "]已下架")
	}
	// 商品需要改变的库存
	var mapProduct *GormModel.TzProd = prodStocksMap[int(prodId)]
	if mapProduct == nil {
		mapProduct = &GormModel.TzProd{}
		mapProduct.TotalStocks = new(int)
		*mapProduct.TotalStocks = 0
		mapProduct.ProdID = &prodId
		mapProduct.ProdName = product.ProdName
	}
	if *product.TotalStocks != -1 {
		*mapProduct.TotalStocks = *mapProduct.TotalStocks + shopCartItem.ProdCount
		prodStocksMap[int(prodId)] = mapProduct
	}

	// -1为无限库存
	if *product.TotalStocks != -1 && *mapProduct.TotalStocks > *product.TotalStocks {
		panic("商品[" + *product.ProdName + "]库存不足")
	}
	return product
}

/*
getOrderItem
@Description: 获取订单商品信息
*/
func getOrderItem(now time.Time, userId string, orderNumber string, shopId int64, orderProdName *strings.Builder, shopCartItem Dto.ShopCartItemDto, sku GormModel.TzSku, product GormModel.TzProd) GormModel.TzOrderItem {
	var orderItem GormModel.TzOrderItem
	orderItem.ShopID = uint64(shopId)
	orderItem.OrderNumber = orderNumber
	orderItem.ProdID = *sku.ProdID
	orderItem.SkuID = *sku.SkuID
	orderItem.SkuName = *sku.SkuName
	orderItem.ProdCount = shopCartItem.ProdCount
	orderItem.ProdName = *sku.ProdName
	if sku.Pic == nil || *sku.Pic == "" {
		orderItem.Pic = *product.Pic
	} else {
		orderItem.Pic = *sku.Pic
	}
	orderItem.Price = shopCartItem.Price
	orderItem.UserID = userId
	orderItem.ProductTotalAmount = shopCartItem.ProductTotalAmount
	orderItem.RecTime = now
	orderItem.CommSts = 0
	orderItem.BasketDate = &shopCartItem.BasketDate
	//orderProdName.append(orderItem.getProdName()).append(",");
	// 追加 orderItem 的 ProdName 追加逗号
	//orderProdName = orderProdName + orderItem.ProdName + ","
	orderProdName.WriteString(orderItem.ProdName)
	orderProdName.WriteString(",")
	//推广员卡号
	orderItem.DistributionCardNo = shopCartItem.DistributionCardNo
	return orderItem
}

func getOrder(now time.Time, userId string, addrOrderId *uint64, shopCartOrderDto Dto.ShopCartOrderDto, orderNumber string, shopId *uint64, orderProdName strings.Builder, orderItems []GormModel.TzOrderItem) GormModel.TzOrder {
	var order GormModel.TzOrder
	order.ShopID = shopId
	order.OrderNumber = orderNumber
	// 订单商品名称
	order.ProdName = orderProdName.String()
	// 用户id
	order.UserID = userId
	// 商品总额
	order.Total = shopCartOrderDto.Total
	// 实际总额
	order.ActualTotal = &shopCartOrderDto.ActualTotal
	order.Status = Common.UNPAY.Value()
	order.UpdateTime = &now
	order.CreateTime = now
	// 初始化 IsPayed 指针
	payed := 0
	order.IsPayed = &payed
	order.DeleteStatus = 0
	order.ProductNums = &shopCartOrderDto.TotalCount
	order.AddrOrderID = addrOrderId
	var f float64 = (shopCartOrderDto.Total + shopCartOrderDto.Transfee) - shopCartOrderDto.ActualTotal
	order.ReduceAmount = &f
	order.FreightAmount = shopCartOrderDto.Transfee
	order.Remarks = &shopCartOrderDto.Remarks
	order.OrderItems = orderItems
	return order
}
